/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.pedant.SweetAlert;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * the error view
 */
public class ErrorView extends Component {
    private Paint circlePaint;
    private Paint xPaint;

    private int boundWidth;
    private int boundHeight;
    private int strokeWidth = dp2px(3);
    private int xWidth = dp2px(28);
    private int xHeight = dp2px(3);

    private float roundV = 0;
    private float dTime = 0;

    private AnimatorValue roundAnimatorValue;
    private AnimatorValue xAnimatorValue;

    public ErrorView(Context context) {
        this(context, null, null);
    }

    public ErrorView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public ErrorView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
    }

    private void init() {
        circlePaint = new Paint();
        xPaint = new Paint();
        circlePaint.setAntiAlias(true);
        circlePaint.setStyle(Paint.Style.STROKE_STYLE);
        circlePaint.setStrokeWidth(strokeWidth);
        circlePaint.setColor(new Color(0xffF27474));
        xPaint.setAntiAlias(true);
        xPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        xPaint.setStrokeWidth(xHeight);
        xPaint.setColor(new Color(0xffF27474));
        onDraw();
    }

    private void onDraw(){
        addDrawTask(
                (component, canvas) -> {
                    boundWidth = getWidth() - getPaddingLeft() - getPaddingRight();
                    boundHeight = getWidth() - getPaddingTop() - getPaddingBottom();
                    if (boundWidth > boundHeight) {
                        boundHeight = boundWidth;
                    } else {
                        boundWidth = boundHeight;
                    }
                    if (dTime < 400) {
                        circlePaint.setColor(new Color(ColorUtils.cpc(0xffffffff, 0xffF27474, dTime / 400)));
                        canvas.drawOval(
                                new RectFloat(
                                        strokeWidth / 2.0f,
                                        boundHeight / 6 * (1 - roundV) + strokeWidth / 2.0f,
                                        boundWidth - strokeWidth / 2.0f,
                                        boundHeight - boundHeight / 6 * (1 - roundV) - strokeWidth / 2.0f),
                                circlePaint);
                    } else {
                        circlePaint.setColor(new Color(0xffF27474));
                        canvas.drawCircle(boundWidth / 2.0f,boundHeight / 2.0f,boundWidth / 2.0f - strokeWidth / 2.0f,circlePaint);
                    }
                    if (dTime >= 250) {
                        float scale;
                        if (dTime >= 250 && dTime <= 370) {
                            scale = 0.4f + 0.75f * (dTime - 250) / 120;
                        } else if (dTime > 370 && dTime < 450) {
                            scale = 1.15f - 0.15f * (dTime - 370) / 80;
                        } else {
                            scale = 1f;
                        }
                        xPaint.setStrokeWidth(xHeight * scale);
                        canvas.save();
                        canvas.rotate(45, boundWidth / 2, boundHeight / 2);
                        canvas.drawLine(
                                new Point(boundWidth / 2 - (dp2px(14)) * scale, boundHeight / 2),
                                new Point(boundWidth / 2 + (dp2px(14)) * scale, boundHeight / 2),
                                xPaint);
                        canvas.rotate(-90, boundWidth / 2, boundHeight / 2);
                        canvas.drawLine(
                                new Point(boundWidth / 2 - (dp2px(14)) * scale, boundHeight / 2),
                                new Point(boundWidth / 2 + (dp2px(14)) * scale, boundHeight / 2),
                                xPaint);
                        canvas.restore();
                    }
                });
    }

    /**
     * start animator
     */
    public void startAnimator() {
        if (roundAnimatorValue == null) {
            roundAnimatorValue = new AnimatorValue();
            roundAnimatorValue.setDuration(400);
            roundAnimatorValue.setCurveType(Animator.CurveType.DECELERATE);
            roundAnimatorValue.setValueUpdateListener(
                    (animatorValue, v) -> roundV = v);
        }
        if (xAnimatorValue == null) {
            xAnimatorValue = new AnimatorValue();
            xAnimatorValue.setDuration(450);
            xAnimatorValue.setValueUpdateListener(
                    (animatorValue, v) -> {
                        dTime = v * 450;
                        getContext()
                                .getUITaskDispatcher()
                                .asyncDispatch(
                                        () -> invalidate());
                    });
        }
        xAnimatorValue.start();
        roundAnimatorValue.start();
    }

    /**
     * set visibility
     *
     * @param visibility the visibility
     */
    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if (visibility != Component.VISIBLE) {
            if (xAnimatorValue != null && xAnimatorValue.isRunning()) {
                xAnimatorValue.stop();
            }
            if (roundAnimatorValue != null && roundAnimatorValue.isRunning()) {
                roundAnimatorValue.stop();
            }
        }
    }

    private int dp2px(float dp) {
        return (int) (getResourceManager().getDeviceCapability().screenDensity / 160 * dp);
    }
}
